Applied patch from Jan Heller that improves logic of go_fishing code
authorØyvind Kolås <ok@src.gnome.org>
Tue, 8 Apr 2008 17:01:23 +0000 (17:01 +0000)
committerØyvind Kolås <ok@src.gnome.org>
Tue, 8 Apr 2008 17:01:23 +0000 (17:01 +0000)
in babl-fish.c. The current code searches list of all fishes while
looking for suitable preexistent BABL_FISH_PATH instance. The new code
only searches relevant part of database's hash table. Further, the
current code searches for fish path every time such a babl fish is
requested, even though the same fish path has been requested before
and not found. The new code creates dummy BABL_FISH instance with
appropriate source/destination formats and inserts it into the fish
database to indicate that fish path has been searched for and not
found.
* babl/babl-fish.c: (find_fish_path), (find_memcpy_fish),
(babl_fish_get_id), (babl_fish):
* babl/babl-fish-path.c: (babl_fish_path):
* babl/babl-fish-reference.c: (babl_fish_reference):
* babl/babl-fish-simple.c: (babl_fish_simple):
* babl/babl-internal.h:

svn path=/trunk/; revision=304

ChangeLog
babl/babl-fish-path.c
babl/babl-fish-reference.c
babl/babl-fish-simple.c
babl/babl-fish.c
babl/babl-internal.h

index 550b4e9bb02c8cd0101edd886bf3a9143bad1695..ccb2a20e9173a72e3a826daf14ff6ef0c297b0a4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2008-04-08  Øyvind Kolås  <pippin@gimp.org>
+
+       Applied patch from Jan Heller that improves logic of go_fishing code
+       in babl-fish.c. The current code searches list of all fishes while
+       looking for suitable preexistent BABL_FISH_PATH instance. The new code
+       only searches relevant part of database's hash table. Further, the
+       current code searches for fish path every time such a babl fish is
+       requested, even though the same fish path has been requested before
+       and not found. The new code creates dummy BABL_FISH instance with
+       appropriate source/destination formats and inserts it into the fish
+       database to indicate that fish path has been searched for and not
+       found. 
+
+       * babl/babl-fish.c: (find_fish_path), (find_memcpy_fish),
+       (babl_fish_get_id), (babl_fish):
+       * babl/babl-fish-path.c: (babl_fish_path):
+       * babl/babl-fish-reference.c: (babl_fish_reference):
+       * babl/babl-fish-simple.c: (babl_fish_simple):
+       * babl/babl-internal.h:
+
 2008-04-06  Sven Neumann  <sven@gimp.org>
 
        * acinclude.m4: new file defining BABL_DETECT_CFLAGS() macro.
index a0a85829f61b94590aa1a580ac06e18529fe83a7..2380b933337321ed4be0fae989798256e93b4b68 100644 (file)
@@ -193,9 +193,10 @@ Babl *
 babl_fish_path (const Babl *source,
                 const Babl *destination)
 {
-  Babl           *babl = NULL;
-  char           *name = create_name (source, destination, 1);
+  Babl *babl = NULL;
+  char *name;
 
+  name = create_name (source, destination, 1);
   babl = babl_db_exist_by_name (babl_fish_db (), name);
   if (babl) 
     {
@@ -205,17 +206,11 @@ babl_fish_path (const Babl *source,
       return babl;
     }
 
-  babl_assert (BABL_IS_BABL (source));
-  babl_assert (BABL_IS_BABL (destination));
-
-  babl_assert (source->class_type == BABL_FORMAT);
-  babl_assert (destination->class_type == BABL_FORMAT);
-
   babl = babl_calloc (1, sizeof (BablFishPath) +
                       strlen (name) + 1);
 
   babl->class_type                = BABL_FISH_PATH;
-  babl->instance.id               = 0;
+  babl->instance.id               = babl_fish_get_id (source, destination);
   babl->instance.name             = ((char *) babl) + sizeof (BablFishPath);
   strcpy (babl->instance.name, name);
   babl->fish.source               = source;
index bf1bc8062a8a0efdbd73a635b787d9d12bdb4a66..c62a0a6bcdac214d9c98e9f3ebc6d98825e99664 100644 (file)
@@ -69,7 +69,7 @@ babl_fish_reference (const Babl *source,
   babl = babl_malloc (sizeof (BablFishReference) +
                       strlen (name) + 1);
   babl->class_type    = BABL_FISH_REFERENCE;
-  babl->instance.id   = 0;
+  babl->instance.id   = babl_fish_get_id (source, destination);
   babl->instance.name = ((char *) babl) + sizeof (BablFishReference);
   strcpy (babl->instance.name, name);
   babl->fish.source      = source;
index 6c933d858c9eb3a9885556dfac1f16ed53055f79..42fcd8657f86274f075159e50dc956be8e24d858 100644 (file)
@@ -33,7 +33,6 @@ babl_fish_simple (BablConversion *conversion)
   babl_assert (BABL_IS_BABL (conversion));
 
   name = create_name (conversion);
-
   babl = babl_db_exist_by_name (babl_fish_db (), name);
   if (babl) 
     {
@@ -46,7 +45,7 @@ babl_fish_simple (BablConversion *conversion)
   babl = babl_malloc (sizeof (BablFishSimple) +
                       strlen (name) + 1);
   babl->class_type    = BABL_FISH_SIMPLE;
-  babl->instance.id   = 0;
+  babl->instance.id   = babl_fish_get_id (conversion->source, conversion->destination);
   babl->instance.name = ((char *) babl) + sizeof (BablFishSimple);
   strcpy (babl->instance.name, name);
   babl->fish.source      = conversion->source;
index 7f22ebf99c9f2e322677e118ac12fee68e9125ed..a14fac21e16e1873c24d0fac291ddbebcc10a612 100644 (file)
 #include <string.h>
 #include <stdarg.h>
 
+typedef struct _BablFindFish BablFindFish;
+
+typedef struct _BablFindFish
+{
+  Babl       *fish_path;
+  Babl       *fish_ref;
+  Babl       *fish_fish;
+  int        fishes;
+  const Babl *source;
+  const Babl *destination;
+} _BablFishFish;
+
+
+static int
+match_conversion (Babl *conversion,
+                  void *inout);
+
+static int
+find_fish_path (Babl *item, 
+                void *data);
+
+static int
+find_memcpy_fish (Babl *item, 
+                  void *data);
+
+static int
+each_babl_fish_destroy (Babl *babl,
+                        void *data);
+
+
+/* ====================================== */
+
+
+static int
+find_fish_path (Babl *item, 
+                void *data)
+{
+  BablFindFish *ffish = (BablFindFish *) data;
+  if ((item->fish.source == ffish->source) &&
+      (item->fish.destination == ffish->destination))
+    {
+      if (item->instance.class_type == BABL_FISH_REFERENCE)
+        {
+          ffish->fish_ref = item;
+          ffish->fishes++;
+        }  
+      else if (item->instance.class_type == BABL_FISH_PATH)
+        {
+          ffish->fish_path = item;
+          ffish->fishes++;
+        }
+      else if (item->instance.class_type == BABL_FISH)
+        {
+          ffish->fish_fish = item;
+          ffish->fishes++;
+        }
+      if (ffish->fishes == 3)
+        return 1;
+    }
+
+  return 0;
+}
+
+static int
+find_memcpy_fish (Babl *item, 
+                  void *data)
+{
+  BablFindFish *ffish = (BablFindFish *) data;
+  if ((item->fish.source == ffish->source) &&
+      (item->fish.destination == ffish->destination))
+    {
+      if ((item->fish.source == item->fish.destination) &&
+          (item->instance.class_type == BABL_FISH_REFERENCE))
+        {
+          ffish->fish_ref = item;
+          return 1;
+        }  
+    }
+
+  return 0;
+}
 
 static int
 match_conversion (Babl *conversion,
@@ -47,6 +128,20 @@ babl_conversion_find (const void *source,
   return data;
 }
 
+int
+babl_fish_get_id (const Babl *source,
+                  const Babl *destination)
+{
+  /* value of 'id' will be used as argument for hash function,
+   * substraction serves as simple combination of 
+   * source/destination values. */
+  int id = (int) source - (int) destination;
+  /* instances with id 0 won't be inserted into database */
+  if (id == 0)
+    id = 1;
+  return id;
+}
+
 BablDb *
 babl_fish_db (void)
 {
@@ -55,28 +150,6 @@ babl_fish_db (void)
   return db;
 }
 
-static inline Babl *
-go_fishing (const Babl *source,
-            const Babl *destination)
-{
-  BablDb *db = babl_fish_db ();
-  int i;
-
-  for (i = 0; i < db->babl_list->count; i++)
-    {
-      Babl *item = db->babl_list->items[i];
-      if ((void *) source == (void *) item->fish.source &&
-          (void *) destination == (void *) item->fish.destination &&
-          (item->class_type == BABL_FISH_PATH || /* accept only paths */
-           source == destination)                /* or memcpy */
-          )
-        {
-          return item;
-        }
-    }
-  return NULL;
-}
-
 Babl *
 babl_fish (const void *source,
            const void *destination,
@@ -89,14 +162,10 @@ babl_fish (const void *source,
   babl_assert (destination);
 
   if (BABL_IS_BABL (source))
-    {
-      source_format = source;
-    }
+    source_format = source;
 
   if (!source_format)
-    {
-      source_format = babl_format ((char *) source);
-    }
+    source_format = babl_format ((char *) source);
 
   if (!source_format)
     {
@@ -105,14 +174,10 @@ babl_fish (const void *source,
     }
 
   if (BABL_IS_BABL (destination))
-    {
-      destination_format = destination;
-    }
+    destination_format = destination;
 
   if (!destination_format)
-    {
-      destination_format = babl_format ((char *) destination);
-    }
+    destination_format = babl_format ((char *) destination);
 
   if (!destination_format)
     {
@@ -121,41 +186,90 @@ babl_fish (const void *source,
     }
 
   {
-    Babl *lucky;
-    lucky = go_fishing (source_format, destination_format);
-    if (lucky)
-      return lucky;
-  }
+    int            hashval;
+    BablHashTable *id_htable;
+    BablFindFish   ffish = {(Babl *) NULL, 
+                            (Babl *) NULL, 
+                            (Babl *) NULL, 
+                            0,
+                            source_format, 
+                            destination_format};
 
-  if (0) /* do not accept shortcut conversions, since there might be
-            a faster path, besides the shortcut conversion might
-            have a too large error, let's rely on the paths for
-            error checking.
-          */
-    {
-      Babl *shortcut_conversion;
+    id_htable = (babl_fish_db ())->id_hash;
+    hashval = babl_hash_by_int (id_htable, babl_fish_get_id (source_format, destination_format));
 
-      shortcut_conversion = babl_conversion_find (
-        source_format, destination_format);
-
-      if (shortcut_conversion)
-        {
-          return babl_fish_simple (&(shortcut_conversion->conversion));
-        }
-    }
+    if (source_format == destination_format)
+      {
+        /* In the case of equal source and destination formats
+         * we will search through the fish database for reference fish 
+         * to handle the memcpy */
+        id_htable->find_func = find_memcpy_fish;
+        babl_hash_table_find (id_htable, hashval, (void *) &ffish);
+      }
+    else 
+      {
+        /* In the case of different source and destination formats
+         * we will search through the fish database for appropriate fish path
+         * to handle the conversion. In the case that preexistent
+         * fish path is found, we'll return it. In the case BABL_FISH
+         * instance with the same source/destination is found, we'll
+         * return reference fish. 
+         * In the case neither fish path nor BABL_FISH path are found, 
+         * we'll try to construct new fish path for requested 
+         * source/destination. In the case new fish path is found, we'll
+         * return it, otherwise we'll create dummy BABL_FISH instance and
+         * insert it into the fish database to indicate non-existent fish
+         * path.
+         */
+        id_htable->find_func = find_fish_path;
+        babl_hash_table_find (id_htable, hashval, (void *) &ffish);
 
-  {
-    Babl *fish_path;
+        if (ffish.fish_path)
+          {
+            /* we have found suitable fish path in the database */
+            return ffish.fish_path;
+          }  
+        if (!ffish.fish_fish)
+          {
+            /* we haven't tried to search for suitable path yet */
+            Babl *fish_path = babl_fish_path (source_format, destination_format);
 
-    fish_path = babl_fish_path (source_format, destination_format);
+            if (fish_path)
+              {
+                return fish_path;
+              }
+            else 
+              {
+                /* there isn't a suitable path for requested formats,
+                 * let's create a dummy BABL_FISH instance and insert
+                 * it into the fish database to indicate that such path
+                 * does not exist.
+                 */
+                char *name = "X"; /* name does not matter */
+                Babl *fish = babl_calloc (1, sizeof (BablFish) + strlen (name) + 1);
+                
+                fish->class_type                = BABL_FISH;
+                fish->instance.id               = babl_fish_get_id (source_format, destination_format);
+                fish->instance.name             = ((char *) fish) + sizeof (BablFish);
+                strcpy (fish->instance.name, name);
+                fish->fish.source               = source_format;
+                fish->fish.destination          = destination_format;
+                babl_db_insert (babl_fish_db (), fish);
+              }
+          }
+      }
 
-    if (fish_path)
+    if (ffish.fish_ref)
+      {
+        /* we have already found suitable reference fish */
+        return ffish.fish_ref;
+      }
+    else 
       {
-        return fish_path;
+        /* we have to create new reference fish */
+        return babl_fish_reference (source_format, destination_format);
       }
   }
-
-  return babl_fish_reference (source_format, destination_format);
 }
 
 long
@@ -164,7 +278,7 @@ babl_fish_process (Babl *babl,
                    void *destination,
                    long  n)
 {
-  long       ret               = 0;
+  long ret = 0;
 
   switch (babl->class_type)
     {
index 72d6a7904a38d05aec3c3c0314010fabe299c4d1..1d0e28189c03c1dae26ce9d7f168b77019476016 100644 (file)
@@ -88,6 +88,8 @@ long     babl_fish_path_process         (Babl           *babl,
                                          void           *source,
                                          void           *destination,
                                          long            n);
+int      babl_fish_get_id               (const Babl     *source,
+                                         const Babl     *destination);
 
 double   babl_format_loss               (Babl           *babl);
 Babl   * babl_image_from_linear         (char           *buffer,